package org.example.what_mall.service.impl;

import cn.hutool.crypto.SmUtil;
import com.auth0.jwt.JWT;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.example.what_mall.dto.GoodsForm;
import org.example.what_mall.dto.GoodsUpdateForm;
import org.example.what_mall.dto.ReplyForm;
import org.example.what_mall.dto.UpdatePwdForm;
import org.example.what_mall.entity.*;
import org.example.what_mall.enums.MessageState;
import org.example.what_mall.enums.OrderState;
import org.example.what_mall.exception.GlobalCode;
import org.example.what_mall.exception.GlobalException;
import org.example.what_mall.mapper.*;
import org.example.what_mall.service.IAdminService;
import org.example.what_mall.util.RedisConstant;
import org.example.what_mall.util.UserHolder;
import org.example.what_mall.util.WordUtil;
import org.example.what_mall.vo.MessageVO;
import org.example.what_mall.vo.OneOrderInfoVO;
import org.example.what_mall.vo.OrderInfoVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class AdminServiceImpl implements IAdminService {
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private GoodsMapper goodsMapper;
    @Autowired
    private SpecMapper specMapper;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private MessageMapper messageMapper;
    @Autowired
    private ReplyMapper replyMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public List<Category> getTypes() {
        return categoryMapper.selectList(null);
    }

    @Transactional
    @Override
    public void changePwd(UpdatePwdForm form) {
        String keyword = RedisConstant.USER_TOKE_PREFIX + form.getAdminToken();
        Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries(keyword);
        Integer userId = Integer.parseInt(entries.get("id").toString());

        User user = userMapper.selectById(userId);

        String cOldPwd = SmUtil.sm3(form.getOldPwd());
        if(!cOldPwd.equals(user.getPwd())){
            throw new GlobalException(400, "原密码错误或两次输入不一致");
        }
        if(!form.getNewPwd().equals(form.getConfirmPwd())){
            throw new GlobalException(400, "原密码错误或两次输入不一致");
        }

        String cNewPwd = SmUtil.sm3(form.getNewPwd());

        userMapper.update(new LambdaUpdateWrapper<User>().eq(User::getId, userId).set(User::getPwd, cNewPwd));
    }

    @Override
    public List<User> getAllUser() {
        return userMapper.selectList(null);
    }

    @Override
    public List<User> searchUser(String word) {
        return userMapper.selectList(new LambdaQueryWrapper<User>()
                .like(User::getNickname, word).or()
                .like(User::getEmail, word).or()
                .like(User::getPhone, word));
    }

    @Transactional
    @Override
    public void deleteUser(Integer id) {
        User user = userMapper.selectById(id);
        if(user == null){
            throw new GlobalException(404, "用户不存在");
        }
        userMapper.deleteById(id);
    }

    @Transactional
    @Override
    public void addType(Category category) {
        Category category1 = categoryMapper.selectOne(new LambdaQueryWrapper<Category>().eq(Category::getName, category.getName()));
        if(category1 != null){
            throw new GlobalException(400, "类目已存在");
        }

        categoryMapper.insert(category);
    }

    @Transactional
    @Override
    public void addGoods(GoodsForm form) {
        Goods goods = Goods.builder()
                .desc(form.getDesc())
                .img(form.getImg())
                .name(form.getName())
                .typeId(form.getTypeId())
                .build();
        goodsMapper.insert(goods);

//        System.out.println(goods);

        List<Spec> specList = form.getSpecList();
        specList.forEach(spec -> {spec.setGoodsId(goods.getId());});

        String description = form.getName().concat(form.getDesc());
        List<String> words = WordUtil.getInstance().word(description);
        words.forEach(word -> {
            stringRedisTemplate.opsForSet().add(RedisConstant.GOODS_WORD_PREFIX+word, goods.getId().toString());
        });

        specMapper.insert(specList);
    }

    @Transactional
    @Override
    public void updateGoods(GoodsUpdateForm form) {
        Goods goods = Goods.builder()
                .desc(form.getDesc())
                .img(form.getImg())
                .name(form.getName())
                .typeId(form.getTypeId())
                .id(form.getId())
                .build();
        goodsMapper.updateById(goods);

        String description = form.getName().concat(form.getDesc());
        List<String> words = WordUtil.getInstance().word(description);
        words.forEach(word -> {
            stringRedisTemplate.opsForSet().add(RedisConstant.GOODS_WORD_PREFIX+word, goods.getId().toString());
        });

        List<Spec> specList = form.getSpecList().stream().filter(spec -> !(spec.getSpecName()==null||spec.getSpecName().isEmpty())).toList();
        specList.forEach(spec -> {spec.setGoodsId(goods.getId());});
        specMapper.insertOrUpdate(specList);
    }

    @Transactional
    @Override
    public Spec addSpec(Spec spec) {
        Goods g = goodsMapper.selectById(spec.getGoodsId());
        if(g == null){
            throw new GlobalException(404, "商品不存在");
        }
        specMapper.insert(spec);
        return spec;
    }

    @Transactional
    @Override
    public void deleteSpec(Spec spec) {
        Spec spec1 = specMapper.selectOne(new LambdaQueryWrapper<Spec>().eq(Spec::getGoodsId, spec.getGoodsId()).eq(Spec::getSpecName, spec.getSpecName()));
        if(spec1 == null){
            throw new GlobalException(404, "规格不存在");
        }
        specMapper.deleteById(spec1);
    }

    @Override
    public void deleteGoods(Integer id) {
        int i = goodsMapper.deleteById(id);
        if(i != 1){
            throw new GlobalException(404, "商品不存在");
        }
        specMapper.delete(new LambdaQueryWrapper<Spec>().eq(Spec::getGoodsId, id));
    }

    @Override
    public List<OrderInfoVO> getOrderByState(Integer state) {
        List<Order> orders;
        if(state == OrderState.ALL.getCode())
        {
            orders = orderMapper.selectList(null);
        }
        else orders = orderMapper.selectList(new LambdaQueryWrapper<Order>().eq(Order::getState, state));

        List<OrderInfoVO> orderInfoVOS = new ArrayList<>();

        for (Order order : orders) {
            User user = userMapper.selectById(order.getBuyerId());
            Spec spec = specMapper.selectById(order.getGoodsDetailId());
            if(spec==null) continue;
            Goods goods = goodsMapper.selectById(spec.getGoodsId());
            if(goods == null) continue;

            OrderInfoVO orderInfoVO = OrderInfoVO.of(order, user, goods.getName(), spec.getSpecName());
            orderInfoVOS.add(orderInfoVO);
        }

        return orderInfoVOS;
    }

    @Override
    public OneOrderInfoVO getOrder(Integer id) {
        Order order = orderMapper.selectById(id);
        User user = userMapper.selectById(order.getBuyerId());
        Spec spec = specMapper.selectById(order.getGoodsDetailId());
        if(spec == null) throw new GlobalException(GlobalCode.PARAMETER_FAIL);

        Goods goods = goodsMapper.selectById(spec.getGoodsId());

        if(goods == null) throw new GlobalException(GlobalCode.PARAMETER_FAIL);

        return new OneOrderInfoVO(order, user, goods, spec);
    }

    @Transactional
    @Override
    public void changeOrder(Order order) {
        int i = orderMapper.updateById(order);
        if(i != 1){
            throw new GlobalException(404, "订单不存在");
        }
    }

    @Transactional
    @Override
    public void deleteOrder(Integer id) {
        int i = orderMapper.deleteById(id);
        if(i != 1){
            throw new GlobalException(404, "订单不存在");
        }
    }

    @Override
    public List<MessageVO> noReplyMessage() {
        List<Message> messages = messageMapper.selectList(new LambdaQueryWrapper<Message>().eq(Message::getState, MessageState.UNREPLIED.getCode()));
        List<MessageVO> messageVOS = new ArrayList<>();
        for (Message message : messages) {
            User user = userMapper.selectById(message.getUserId());
            Goods goods = goodsMapper.selectById(message.getGoodsId());
            MessageVO vo = new MessageVO(message.getId(), user, goods, message.getContent(), message.getTime(), "");
            messageVOS.add(vo);
        }
        return messageVOS;
    }

    @Override
    public List<MessageVO> RepliedMessage() {
        List<Message> messages = messageMapper.selectList(new LambdaQueryWrapper<Message>().eq(Message::getState, MessageState.REPLIED.getCode()));
        List<MessageVO> messageVOS = new ArrayList<>();
        for (Message message : messages) {
            User user = userMapper.selectById(message.getUserId());
            Goods goods = goodsMapper.selectById(message.getGoodsId());
            Reply reply = replyMapper.selectOne(new LambdaQueryWrapper<Reply>().eq(Reply::getMessageId, message.getId()).last("limit 1"));
            MessageVO vo = new MessageVO(message.getId(), user, goods, message.getContent(), message.getTime(), reply.getContent());
            messageVOS.add(vo);
        }
        return messageVOS;
    }

    @Transactional
    @Override
    public void reply(ReplyForm form) {
        messageMapper.update(new LambdaUpdateWrapper<Message>().set(Message::getState, MessageState.REPLIED.getCode()).eq(Message::getId, form.getId()));
        Reply r = Reply.builder()
                .content(form.getContent())
                .messageId(form.getId())
                .userId(UserHolder.getUser().getId())
                .build();
        replyMapper.insert(r);
    }
}
